﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Data;
using ParseControls;

namespace ParseOnlineAdmin
{
    public class BaseDataContext : INotifyPropertyChanged
    {
        // ctr 
        public BaseDataContext()
            : base()
        { }

        // Interface 
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    public class ParseDataContext : BaseDataContext
    {
        // Fields 
        ListSortDirection sortDirection = ListSortDirection.Ascending;
        bool isGrouped = true;

        // Properties 
        #region Properties


        // Apps 
        private object _SelectedApp = null;
        public object SelectedApp
        {
            get { return _SelectedApp; }
            set
            {
                _SelectedApp = value;
                NotifyPropertyChanged("SelectedApp");
            }
        }

        private ObservableCollection<object> _AppItems = new ObservableCollection<object>();
        public ObservableCollection<object> AppItems
        {
            get { return _AppItems; }
            set
            {
                _AppItems = value;
                NotifyPropertyChanged();
            }
        }

        // Class 
        private object _SelectedClass = null;
        public object SelectedClass
        {
            get { return _SelectedClass; }
            set
            {
                _SelectedClass = value;
                NotifyPropertyChanged("SelectedClass");
            }
        }

        private ObservableCollection<object> _ClassItems = new ObservableCollection<object>();
        public ObservableCollection<object> ClassItems
        {
            get { return _ClassItems; }
            set
            {
                _ClassItems = value;
                NotifyPropertyChanged();
            }
        }

        // Assign Item 
        private object _ToSelectClass = null;
        public object ToSelectClass
        {
            get { return _ToSelectClass; }
            set
            {
                _ToSelectClass = value;
                NotifyPropertyChanged("ToSelectClass");
            }
        }

        private ObservableCollection<object> _ToSelectClassItems = new ObservableCollection<object>();
        public ObservableCollection<object> ToSelectClassItems
        {
            get { return _ToSelectClassItems; }
            set
            {
                _ToSelectClassItems = value;
                NotifyPropertyChanged();
            }
        }

        private object _ToAssignSelectedItem = null;
        public object ToAssignSelectedItem
        {
            get { return _ToAssignSelectedItem; }
            set
            {
                _ToAssignSelectedItem = value;
                NotifyPropertyChanged("ToAssignSelectedItem");
            }
        }

        private ObservableCollection<object> _ToAssignItems = new ObservableCollection<object>();
        public ObservableCollection<object> ToAssignItems
        {
            get { return _ToAssignItems; }
            set
            {
                _ToAssignItems = value;
                NotifyPropertyChanged();
            }
        }

        // RelatedTask 
        private object _SelectedRelatedTask = null;
        public object SelectedRelatedTask
        {
            get { return _SelectedRelatedTask; }
            set
            {
                _SelectedRelatedTask = value;
                NotifyPropertyChanged("SelectedRelatedTask");
            }
        }

        private ObservableCollection<object> _RelatedTaskItems = new ObservableCollection<object>();
        public ObservableCollection<object> RelatedTaskItems
        {
            get { return _RelatedTaskItems; }
            set
            {
                _RelatedTaskItems = value;
                NotifyPropertyChanged();
            }
        }

        // RelatedProperty 
        private object _SelectedRelatedProperty = null;
        public object SelectedRelatedProperty
        {
            get { return _SelectedRelatedProperty; }
            set
            {
                _SelectedRelatedProperty = value;
                NotifyPropertyChanged("SelectedRelatedProperty");
            }
        }

        private ObservableCollection<object> _RelatedPropertyItems = new ObservableCollection<object>();
        public ObservableCollection<object> RelatedPropertyItems
        {
            get { return _RelatedPropertyItems; }
            set
            {
                _RelatedPropertyItems = value;
                NotifyPropertyChanged();
            }
        }

        // RelatedComment 
        private object _SelectedRelatedComment = null;
        public object SelectedRelatedComment
        {
            get { return _SelectedRelatedComment; }
            set
            {
                _SelectedRelatedComment = value;
                NotifyPropertyChanged("SelectedRelatedComment");
            }
        }

        private ObservableCollection<object> _RelatedCommentItems = new ObservableCollection<object>();
        public ObservableCollection<object> RelatedCommentItems
        {
            get { return _RelatedCommentItems; }
            set
            {
                _RelatedCommentItems = value;
                NotifyPropertyChanged();
            }
        }

        // RelatedItem 
        private object _SelectedRelatedItem = null;
        public object SelectedRelatedItem
        {
            get { return _SelectedRelatedItem; }
            set
            {
                _SelectedRelatedItem = value;
                NotifyPropertyChanged("SelectedRelatedItem");
            }
        }

        private ObservableCollection<object> _RelatedItemItems = new ObservableCollection<object>();
        public ObservableCollection<object> RelatedItemItems
        {
            get { return _RelatedItemItems; }
            set
            {
                _RelatedItemItems = value;
                NotifyPropertyChanged();
            }
        }

        // RelatedFile 
        private object _SelectedRelatedFile = null;
        public object SelectedRelatedFile
        {
            get { return _SelectedRelatedFile; }
            set
            {
                _SelectedRelatedFile = value;
                NotifyPropertyChanged("SelectedRelatedFile");
            }
        }

        private ObservableCollection<object> _RelatedFileItems = new ObservableCollection<object>();
        public ObservableCollection<object> RelatedFileItems
        {
            get { return _RelatedFileItems; }
            set
            {
                _RelatedFileItems = value;
                NotifyPropertyChanged();
            }
        }

        // Matchcode 
        private string _Matchcode = string.Empty;
        public string Matchcode
        {
            get { return _Matchcode; }
            set
            {
                _Matchcode = value;
                NotifyPropertyChanged();
            }
        }
        #endregion

        // Items 
        #region Items
        private object _SelectedItem = null;
        public object SelectedItem
        {
            get { return _SelectedItem; }
            set
            {
                _SelectedItem = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<object> _Items = new ObservableCollection<object>();
        public ObservableCollection<object> Items
        {
            get { return _Items; }
            set
            {
                _Items = value;
                NotifyPropertyChanged();
            }
        }

        private CollectionView _view;

        private object _SelectedDoneItem = null;
        public object SelectedDoneItem
        {
            get { return _SelectedDoneItem; }
            set
            {
                _SelectedDoneItem = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<object> _DoneItems = new ObservableCollection<object>();
        public ObservableCollection<object> DoneItems
        {
            get { return _DoneItems; }
            set
            {
                _DoneItems = value;
                NotifyPropertyChanged();
            }
        }
        #endregion

        // ctr 
        public ParseDataContext()
            : base()
        {
            // Events 
            this.PropertyChanged += OnPropChanged;

            // Events 
            ParseOne.Instance.InformationSend += OnInformationSend;

            // Methods 
            this.LoadApps();
            this.LoadToAssignClasses();
        }

        // Events 
        void OnPropChanged(object sender, PropertyChangedEventArgs e)
        {
            // App 
            if (e.PropertyName == "SelectedApp")
            {
                if (this.SelectedApp != null)
                {
                    // Register App 
                    ParseHelper.RegisterApp((ParseApp)this.SelectedApp);

                    this.Items.Clear();

                    // Load Classes 
                    this.LoadClasses();
                }
            }

            // Class 
            if (e.PropertyName == "SelectedClass")
            {
                // Load Items 
                this.LoadItems();
            }

            // To Assign Class 
            if (e.PropertyName == "ToSelectClass")
            {
                ParseClass _cl = this.ToSelectClass as ParseClass;
                if (_cl != null)
                {
                    this.LoadToAssignItems(_cl.Name);
                }
            }

            // Item 
            if (e.PropertyName == "SelectedItem")
            {
                // Tasks 
                this.LoadRelatedTasks();

                // Files 
                this.LoadRelatedFiles();

                // Related Items 
                this.LoadRelatedItems();

                // Comments 
                this.LoadRelatedComments();
            }

            // Matchcode 
            if (e.PropertyName == "Matchcode")
            {
                this.LoadItems();
            }

            // Task 
            if (e.PropertyName == "SelectedRelatedTask")
            {
                ParseCustomEventArgs args = new ParseCustomEventArgs("Task:Edit:View:Show");
                args.Object = this.SelectedRelatedTask;
                ParseOne.InformationSending(args);
            }
        }
        void OnInformationSend(object sender, ParseCustomEventArgs e)
        {
            if (e.IsHandled)
                return;

            // apps 
            if (e.Command == "Apps:Refresh")
            {
                this.LoadApps();
                e.IsHandled = true;
                return;
            }

            // classes 
            if (e.Command == "Classes:Refresh")
            {
                this.LoadClasses();
                e.IsHandled = true;
                return;
            }

            // Assign 
            if (e.Command == "Assign:RelatedItem")
            {
                this.AssignItemToRelated();

                e.IsHandled = true;
                return;
            }

            // Create Item 
            if (e.Command == "Create:by:Matchcode")
            {
                this.CreateItem(this.Matchcode, ((ParseClass)this.SelectedClass).Name);

                e.IsHandled = true;
                return;
            }

            // Create Task 
            if (e.Command == "Task:New")
            {
                this.CreateNewTask(e.Parameter);

                e.IsHandled = true;
                return;
            }

            // Create Comment 
            if (e.Command == "Comment:New")
            {
                this.CreateNewComment(e.Parameter);

                e.IsHandled = true;
                return;
            }

            // Reload Related Files 
            if (e.Command == "RelatedFiles:Reload")
            {
                this.LoadRelatedFiles();

                e.IsHandled = true;
                return;
            }

            // Save 
            if (e.Command == "Save:Current:Parse:Object")
            {
                this.SaveItem();

                e.IsHandled = true;
                return;
            }

            // Delete 
            if (e.Command == "Delete:Current:Parse:Object")
            {
                this.DeleteItem();

                // Load 
                this.LoadItems();

                e.IsHandled = true;
                return;
            }

            // Sortierung 
            if (e.Command == "Sort:Current:Items")
            {
                // Sort Direction 
                sortDirection = (sortDirection == ListSortDirection.Ascending)
                                    ? ListSortDirection.Descending
                                    : ListSortDirection.Ascending;
                // Load 
                this.LoadItems();

                e.IsHandled = true;
                return;
            }

            // Gruppierung 
            if (e.Command == "Group:Current:Items")
            {
                // Gruppierung 
                isGrouped = (isGrouped == true) ? false : true;

                // Load 
                this.LoadItems();

                e.IsHandled = true;
                return;
            }

            // Delete App 
            if (e.Command == "App:Current:Delete")
            {
                this.DeleteApp();

                e.IsHandled = true;
                return;
            }

            // Refresh Tasks  
            if (e.Command == "Items:Refresh")
            {
                this.LoadItems();

                e.IsHandled = true;
                return;

            }
            // Refresh Tasks  
            if (e.Command == "Task:Refresh")
            {
                this.LoadRelatedTasks();

                e.IsHandled = true;
                return;
            }

            // Class Delete 
            if (e.Command == "Class:Delete")
            {
                if (this.SelectedClass != null)
                {
                    ParseClass _cl = this.SelectedClass as ParseClass;
                    if (_cl != null)
                    {
                        ParseOne.Package.Classes.Remove(_cl);
                        ParseOne.Package.Save();
                        ParseOne.ReloadPackage();

                        this.LoadClasses();
                    }
                }

                e.IsHandled = true;
                return;
            }
        }

        // Apps 
        private void LoadApps()
        {
            AppItems.Clear();
            foreach (ParseApp app in ParseOne.Package.Apps)
            {
                AppItems.Add(app);
            }

            if (this.AppItems.Count >= 1)
            {
                this.SelectedApp = this.AppItems[0];
            }
        }
        private void DeleteApp()
        {
            if (this.SelectedApp != null)
            {
                ParseApp pa = this.SelectedApp as ParseApp;
                if (pa == null)
                    return;

                // Remove 
                ParseOne.Package.Apps.Remove(pa);

                // Save 
                ParseOne.Package.Save();

                // Reload 
                ParseOne.ReloadPackage();

                // Reload Classes 
                this.LoadClasses();
            }
        }

        // Classes 
        private void LoadClasses()
        {
            this.ClassItems.Clear();

            ParseApp app = this.SelectedApp as ParseApp;

            if (app != null)
            {
                foreach (ParseClass Class in ParseOne.Package.Classes
                    .Where(item => item.ParseAppGUID == app.GUID))
                {
                    ClassItems.Add(Class);
                }

                if (this.ClassItems.Count >= 1)
                {
                    this.SelectedClass = this.ClassItems[0];
                }
            }


        }
        private void CreateClass(string name)
        {
            // App 
            if (this.SelectedApp == null)
                return;

            // Class 
            ParseClass _class = new ParseClass();
            _class.GUID = Guid.NewGuid();
            _class.Name = name;
            _class.ParseAppGUID = ((ParseApp)this.SelectedApp).GUID;

            // Package 
            ParseOne.Package.Classes.Add(_class);
            ParseOne.Package.Save();
            ParseOne.ReloadPackage();

            // Items 
            LoadClasses();
        }

        // Items 
        public async void LoadItems()
        {
            try
            {
                this.Items.Clear();
                this.DoneItems.Clear();

                ParseClass _class = this.SelectedClass as ParseClass;
                if (_class == null)
                    return;

                ParseApp _app = this.SelectedApp as ParseApp;
                if (_app == null)
                    return;

                ObservableCollection<object> _doneItems = new ObservableCollection<object>();

                List<ParseObjectMask> items = await ParseObjectMask.SearchItemsByTypeAsync(this.Matchcode, _class.Name, _app);
                if (items != null)
                {
                    foreach (ParseObjectMask item in items)
                    {
                        if (item.IsChecked == true)
                        {
                            _doneItems.Add(item);
                        }
                        else
                        {
                            this.Items.Add(item);
                        }
                    }
                }

                this.DoneItems = _doneItems;

                _view = (CollectionView)CollectionViewSource.GetDefaultView(this.Items);
                _view.GroupDescriptions.Clear();
                _view.SortDescriptions.Clear();

                if (isGrouped)
                {
                    PropertyGroupDescription groupDescription = new PropertyGroupDescription("Category");
                    _view.GroupDescriptions.Add(groupDescription);
                }

                SortDescription sortDescription = new SortDescription("Title", sortDirection);
                _view.SortDescriptions.Add(sortDescription);
            }
            catch (Exception ex)
            {

            }
        }
        public async void CreateItem(string title, string type)
        {
            // check App 
            if (this.SelectedApp == null)
                return;

            // check Class 
            if (this.SelectedClass == null)
                return;

            // create new Item 
            ParseObjectMask no = await ParseObjectMask.CreateItemAsync(title, type, (ParseApp)this.SelectedApp);

            await Task.Delay(1000);

            // Items 
            this.LoadItems();
        }
        public async void SaveItem()
        {
            if (this.SelectedItem != null)
            {
                ParseApp pa = this.SelectedApp as ParseApp;
                if (pa == null)
                    return;

                ParseObjectMask po = this.SelectedItem as ParseObjectMask;
                if (po == null)
                    return;

                await ParseObjectMask.UpdateItemAsync(po, pa);
            }
        }
        public async void DeleteItem()
        {
            if (this.SelectedItem != null)
            {
                ParseApp pa = this.SelectedApp as ParseApp;
                if (pa == null)
                    return;

                ParseObjectMask po = this.SelectedItem as ParseObjectMask;
                if (po == null)
                    return;

                await ParseObjectMask.DeleteItemAsync(po, pa);
            }
        }

        // Tasks 
        public async void LoadRelatedTasks()
        {
            try
            {
                this.RelatedTaskItems.Clear();

                ParseApp _app = this.SelectedApp as ParseApp;
                if (_app == null)
                    return;

                ParseObjectMask _po = this.SelectedItem as ParseObjectMask;
                if (_po == null)
                    return;

                List<ParseObjectMask> items = await ParseObjectMask.GetRelatedItemsByTypeAsync(_po, "Task", _app);
                if (items != null)
                {
                    foreach (ParseObjectMask item in items)
                    {
                        this.RelatedTaskItems.Add(item);
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }
        public async void CreateNewTask(string title)
        {
            // check App 
            if (this.SelectedApp == null)
                return;

            ParseApp app = this.SelectedApp as ParseApp;
            if (app == null)
                return;

            // check Class 
            if (this.SelectedClass == null)
                return;

            // check Parent 
            if (this.SelectedItem == null)
                return;

            ParseObjectMask parent = this.SelectedItem as ParseObjectMask;
            if (parent == null)
                return;

            // create new Item 
            ParseObjectMask child = await ParseObjectMask.CreateItemAsync(title, "Task", (ParseApp)this.SelectedApp);
            ParseObjectMask.AssignItemAsync(parent, child, app);

            await Task.Delay(500);

            this.LoadRelatedTasks();
        }

        // Comments 
        public async void LoadRelatedComments()
        {
            try
            {
                this.RelatedCommentItems.Clear();

                ParseApp _app = this.SelectedApp as ParseApp;
                if (_app == null)
                    return;

                ParseObjectMask _po = this.SelectedItem as ParseObjectMask;
                if (_po == null)
                    return;

                List<ParseObjectMask> items = await ParseObjectMask.GetRelatedItemsByTypeAsync(_po, "Comment", _app);
                if (items != null)
                {
                    foreach (ParseObjectMask item in items)
                    {
                        this.RelatedCommentItems.Add(item);
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }
        public async void CreateNewComment(string title)
        {
            // check App 
            if (this.SelectedApp == null)
                return;

            ParseApp app = this.SelectedApp as ParseApp;
            if (app == null)
                return;

            // check Class 
            if (this.SelectedClass == null)
                return;

            // check Parent 
            if (this.SelectedItem == null)
                return;

            ParseObjectMask parent = this.SelectedItem as ParseObjectMask;
            if (parent == null)
                return;

            // create new Item 
            ParseObjectMask child = await ParseObjectMask.CreateItemAsync(title, "Comment", (ParseApp)this.SelectedApp);
            ParseObjectMask.AssignItemAsync(parent, child, app);

            await Task.Delay(500);

            this.LoadRelatedComments();
        }

        // RelatedItems 
        public void LoadToAssignClasses()
        {
            this.ToSelectClassItems.Clear();
            foreach (ParseClass Class in ParseOne.Package.Classes)
            {
                ToSelectClassItems.Add(Class);
            }

            if (this.ToSelectClassItems.Count >= 1)
            {
                this.ToSelectClass = this.ToSelectClassItems[0];
            }
        }
        public async void LoadToAssignItems(string type)
        {
            try
            {
                ParseApp _app = this.SelectedApp as ParseApp;
                if (_app == null)
                    return;

                this.ToAssignItems.Clear();
                List<ParseObjectMask> items = await ParseObjectMask.SearchItemsByTypeAsync(this.Matchcode, type, _app);
                if (items != null)
                {
                    foreach (ParseObjectMask item in items)
                    {
                        this.ToAssignItems.Add(item);
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }
        public void AssignItemToRelated()
        {
            // check App 
            if (this.SelectedApp == null)
                return;

            ParseApp app = this.SelectedApp as ParseApp;
            if (app == null)
                return;

            // Parent 
            if (this.SelectedItem == null)
                return;

            ParseObjectMask _parent = this.SelectedItem as ParseObjectMask;
            if (_parent == null)
                return;

            // Child 
            if (this.ToAssignSelectedItem == null)
                return;

            ParseObjectMask _child = this.ToAssignSelectedItem as ParseObjectMask;
            if (_child == null)
                return;

            // Asign 
            ParseObjectMask.AssignItemAsync(_parent, _child, app);


        }
        public async void LoadRelatedItems()
        {
            try
            {
                this.RelatedItemItems.Clear();

                ParseApp _app = this.SelectedApp as ParseApp;
                if (_app == null)
                    return;

                ParseObjectMask _po = this.SelectedItem as ParseObjectMask;
                if (_po == null)
                    return;

                foreach (ParseClass _class in ParseOne.Package.Classes)
                {
                    List<ParseObjectMask> items = await ParseObjectMask.GetRelatedItemsByTypeAsync(_po, _class.Name, _app);
                    if (items != null)
                    {
                        foreach (ParseObjectMask item in items)
                        {
                            this.RelatedItemItems.Add(item);
                        }
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }

        // Files 
        public async void LoadRelatedFiles()
        {
            try
            {
                this.RelatedFileItems.Clear();

                ParseApp _app = this.SelectedApp as ParseApp;
                if (_app == null)
                    return;

                ParseObjectMask _po = this.SelectedItem as ParseObjectMask;
                if (_po == null)
                    return;

                List<ParseObjectMask> items = await ParseObjectMask.GetRelatedItemsByTypeAsync(_po, "File", _app);
                if (items != null)
                {
                    foreach (ParseObjectMask item in items)
                    {
                        this.RelatedFileItems.Add(item);
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }
    }
}
